package com.kevin.swing.impl;

import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;

import com.kevin.MainFrame;
import com.kevin.model.db.DBTableColumnModel;
import com.kevin.model.db.DBTableModel;
import com.kevin.model.jtable.JTableColumnModel;
import com.kevin.service.EntityService;
import com.kevin.swing.ContentJPanel;
import com.kevin.util.CacheUtil;
import com.kevin.util.ConfigProperties;
import com.kevin.util.JTableUtil;
import com.kevin.util.Utils;

import lombok.extern.log4j.Log4j;

@Log4j
public class ContentStep3JPanel extends ContentJPanel {

    private static final long serialVersionUID = 4865803795120029399L;

    private JLabel outDicLabel = new JLabel("输出目录：");
    private JTextField outDicText = new JTextField();// TextField 目录的路径
    private JButton outDicChooseBtn = new JButton("选择");// 选择
    private JFileChooser jfc = new JFileChooser();// 文件选择器

//    private JLabel searchKeyLabel = new JLabel("关键字：");
//    private JTextField searchText = new JTextField();// 搜素关键字

    private JLabel packageLabel = new JLabel("包名：");
    private JTextField packageText = new JTextField();// 包名

    private JButton refreshBtn = new JButton("重新载入");// 重新载入

    private JButton exportBtn = new JButton("导出");// 选择
    private JCheckBox exportDAOJCB = new JCheckBox();// 生成DAO
    private JLabel exportDAOLabel = new JLabel("生成DAO");

    private SwingWorker<Long, Void> worker;
    // 导出表List，导出时用
    private List<DBTableModel> exportTableList = new ArrayList<>();
    private JComboBox<String> comboBox = new JComboBox<>(); // 下拉列表

    // 右键
    private JPopupMenu popup = new JPopupMenu();
    private JMenuItem openfItem = new JMenuItem("打开目录");

    // java字段类型
    private String[] javaTypeArrs = { "String", "Integer", "Long", "Double", "Float", "Date", "Boolean", "BigDecimal" };
    private List<String> javaTypeList = new ArrayList<>();
    // 扩展java字段类型
    private List<String> extendJavaTypes;

    // 处理过的表
    private List<DBTableColumnModel> fillTableColCache; // 获得三级缓存;
    // 常用字处理
    private Map<String, String> commonWordsMap = new HashMap<>();
    private boolean resetCWMap = false;

    private int searchNum = 0; // 搜索条目

    public ContentStep3JPanel(MainFrame owner) {
        super(owner);
        init();
    }

    protected void init() {
        fillTableColCache = getTableColCache();
        // 获得三级缓存;
        popup.add(openfItem);
        openfItem.addActionListener(e -> {
            if (outDicText.getText() != "") {
                openfile(outDicText.getText());
            }
        });
        setPanel();
    }

    /**
     * 加载java类型设置
     * 
     * @Title loadJavaTypeSet
     * @author 吕凯
     * @date 2016年8月27日 上午11:25:15 void
     */
    private void loadJavaTypeSet() {
        javaTypeList.addAll(Arrays.asList(javaTypeArrs));
        extendJavaTypes = ConfigProperties.getList(ConfigProperties.EXTEND_JAVATYPE);
        if (extendJavaTypes != null && extendJavaTypes.size() > 0) {
            javaTypeList.addAll(extendJavaTypes);
        }
        javaTypeList.stream().forEach(javaType -> comboBox.addItem(javaType));
    }

    /**
     * 加载常用此设置
     * 
     * @Title loadCommonWordsSet
     * @author 吕凯
     * @date 2016年8月27日 上午11:25:28 void
     */
    private void loadCommonWordsSet() {
        // 常用词设置
        Map<String, String> commonWordsMapFromCache = null;
        try {
            commonWordsMapFromCache = CacheUtil.get(ConfigProperties.CACHE_COMMON_WORDS);
        } catch (Exception e1) {
            log.error("获取常用词设置缓存失败！", e1);
        }

        if (commonWordsMapFromCache != null) {
            commonWordsMap.putAll(commonWordsMapFromCache);
        }
    }

    protected void setPanel() {
        logTA = new JTextArea();
        logTA.setLineWrap(true);
        logTA.setBorder(null);
        jsplogTA = new JScrollPane(logTA);

        initJTable();
        setTableColumWidth();

        showtableJSpane = new JScrollPane(showTable);
        showtableJSpane.setPreferredSize(new Dimension(600, 69));

        outDicText.setText(ConfigProperties.getString(ConfigProperties.DICTORY));
        outDicText.setPreferredSize(new Dimension(120, 20));

        // 搜索触发事件
        refreshAction();
        // 导出
        exprotAction();
        // 文件选择
        addChooseOutDic();

        JPanel searchbtnPanel = new JPanel();
        searchbtnPanel.setLayout(new GridBagLayout());
        searchbtnPanel.add(outDicLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,
                new Insets(0, 5, 0, 0), 0, 0));
        searchbtnPanel.add(outDicText, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
                new Insets(0, 0, 0, 0), 0, 0));
        searchbtnPanel.add(outDicChooseBtn, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,
                new Insets(0, 0, 0, 0), 0, 0));
//        searchbtnPanel.add(searchKeyLabel, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,
//                new Insets(0, 0, 0, 0), 0, 0));
//        searchbtnPanel.add(searchText, new GridBagConstraints(4, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
//                new Insets(0, 0, 0, 0), 0, 0));
        searchbtnPanel.add(packageLabel, new GridBagConstraints(5, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,
                new Insets(0, 0, 0, 0), 0, 0));
        searchbtnPanel.add(packageText, new GridBagConstraints(6, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
                new Insets(0, 0, 0, 0), 0, 0));
        packageText.setText("kevin");
        // 打开目录
        addOpenMenuAction();
        JPanel searchPanel = new JPanel();
        exportDAOJCB.setSelected(true);
        searchPanel.add(exportDAOJCB);
        searchPanel.add(exportDAOLabel);
        searchPanel.add(refreshBtn);
        searchPanel.add(exportBtn);
        searchbtnPanel.add(searchPanel, new GridBagConstraints(7, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,
                new Insets(0, 0, 0, 0), 0, 0));

        setLayout(new BorderLayout());
        add(searchbtnPanel, BorderLayout.NORTH);
        add(showtableJSpane, BorderLayout.CENTER);
        add(jsplogTA, BorderLayout.SOUTH);

    }

    private void openfile(String filename) {
        try {
            Desktop.getDesktop().open(new File(filename));
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    /**
     * 
     * 输出文件选择
     * 
     * @Title addChooseOutDic
     * @author 吕凯
     * @date 2016年8月23日 下午3:22:58 void
     */
    private void addChooseOutDic() {
        outDicChooseBtn.addActionListener((e) -> {
            if (e.getSource().equals(outDicChooseBtn)) {// 判断触发方法的按钮是哪个
                if (outDicText.getText() != "") {
                    File file = new File(outDicText.getText());
                    if (file.exists()) {
                        jfc.setCurrentDirectory(file);
                    }
                }
                jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);// 设定只能选择到文件夹
                int state = jfc.showOpenDialog(null);// 此句是打开文件选择器界面的触发语句
                if (state == 1) {
                    return;
                } else {
                    File f = jfc.getSelectedFile();// f为选择到的目录
                    outDicText.setText(f.getAbsolutePath());
                    ConfigProperties.setProperty("dictory", f.getAbsolutePath());
                }
            }
        }); // 添加事件处理
    }

    /**
     * 导出操作
     * 
     * @Title addSearchAction
     * @author 吕凯
     * @date 2016年8月23日 下午3:23:16 void
     */
    private void exprotAction() {
        exportBtn.addActionListener(e -> {
            String pageage = packageText.getText();
            String dic = outDicText.getText();
            int i = JOptionPane.showConfirmDialog(null, "以com.model(或dao)." + pageage + "作为包名的类将导出到" + dic + "，是否继续执行？", "导出实体类",
                    JOptionPane.YES_NO_OPTION);
            if (i == JOptionPane.YES_OPTION) {
                // 搜索
                worker = new SwingWorker<Long, Void>() {

                    @Override
                    protected void done() {
                    }

                    @Override
                    protected Long doInBackground() {
                        try {
                            int succnum = 0;
                            long ts = System.currentTimeMillis();
                            String msg = "成功";
                            boolean canExport = true;
                            File dicFile = new File(dic);
                            if (!dicFile.exists()) {
                                if (!dicFile.mkdirs()) {
                                    msg = "失败（创建该目录失败）";
                                    canExport = false;
                                }
                            } else if (!dicFile.isDirectory()) {
                                msg = "失败（选择的输出目录不是目录）";
                                canExport = false;
                            }
                            if (canExport) {
                                int rowCount = showTable.getRowCount();
                                resetCWMap = false;
                                for (int i = 0; i < rowCount; i++) {
                                    // 列转换对象
                                    JTableColumnModel jColModel = JTableColumnModel.jTable2TableColModel(showTable, i);
                                    exportTableList.stream().forEach(table -> {
                                        table.getColumns().stream()
                                                .filter(tableColumn -> tableColumn.getColumnName().equals(jColModel.getColumnName())
                                                        && tableColumn.getTableName().equals(jColModel.getTableName()))
                                                .forEach(tableColumn -> {
                                                    if (!tableColumn.getExportColName().equals(jColModel.getExportColName())) {
                                                        resetCWMap = true;
                                                        commonWordsMap.put(tableColumn.getExportColName().toLowerCase(),
                                                                jColModel.getExportColName());
                                                    }
                                                    tableColumn.setExportColName(jColModel.getExportColName());
                                                    tableColumn.setJavaDataType(jColModel.getJavaDataType());
                                                    tableColumn.setRemarks(jColModel.getRemarks());
                                                });
                                    });

                                }
                                if (resetCWMap) {// 重新加载缓存
                                    CacheUtil.put(ConfigProperties.CACHE_COMMON_WORDS, commonWordsMap);
                                    clearTableColCache();
                                    exportTableList.stream().forEach(table -> {
                                        addTableColCache(table.getColumns());
                                    });
                                }
                                succnum = EntityService.createEntity(exportTableList, pageage, dic, exportDAOJCB.isSelected());
                            } else {
                                log.error(msg);
                            }
                            msg = "成功（" + dic + "）,生成类" + succnum + "个";
                            long te = System.currentTimeMillis();
                            showlog("导出" + msg + "，共耗时" + Utils.timeFormat(te - ts));
//                            owner.enabledNextStep();
                        } catch (Exception e) {
                            log.error("错误", e);
                        }
                        return null;
                    }

                };
                worker.execute();
            }

        }); // 添加事件处理
    }

    /**
     * 搜索时重置表格内容
     * 
     * @Title resetSearchTable
     * @author 吕凯
     * @date 2016年8月23日 下午3:56:29 void
     */
    private void resetSearchTable() {
        exportTableList.clear();
        index = 0;
        showTableModel = new DefaultTableModel(JTableColumnModel.DEFAULTINFO, JTableColumnModel.COLNAMES);
        showTable.setModel(showTableModel);
        setTableColumWidth();
    }

    /**
     * 搜索表返回内容容器jtable初始化
     * 
     * @Title initJTable
     * @author 吕凯
     * @date 2016年8月23日 下午3:23:27 void
     */
    private void initJTable() {
        showTableModel = new DefaultTableModel(JTableColumnModel.DEFAULTINFO, JTableColumnModel.COLNAMES);
        showTable = new JTable(showTableModel) {
            private static final long serialVersionUID = 1234561111L;

            // 不可编辑
            @Override
            public boolean isCellEditable(int row, int column) {
                if (JTableColumnModel.COLINDEX_EDITABLE.contains(column)) { // 第3（导出字段名）、5（导出字段类型）、6（注释）列可编辑
                    return true;
                }
                return false;
            }

        };

        TableColumnModel tcm = showTable.getColumnModel();
        tcm.getColumn(JTableColumnModel.COLINDEX_JCB).setCellEditor(new DefaultCellEditor(comboBox));
        showTable.setRowHeight(20);
    }

    /**
     * 刷新当前jpanel
     * 
     * @Title addSearchActionListener
     * @author 吕凯
     * @date 2016年8月23日 下午3:21:00 void
     */
    private void refreshAction() {
        refreshBtn.addActionListener(e -> {
            // 重新载入
            worker = new SwingWorker<Long, Void>() {

                @Override
                protected void done() {
                }

                @Override
                protected Long doInBackground() {
                    try {
                        showlog("重新载入中……");
                        clearTableColCache(); // 清空缓存
                        fillData();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return null;
                }

            };
            worker.execute();

        });
    }

    // 填充数据
    public void fillData() {
        searchNum = 0;
        List<String> selectedTables = owner.getSelectedTables();
        if (!selectedTables.isEmpty()) {
            // java转换后的类型
            loadJavaTypeSet();
            // 加载常用词设置
            loadCommonWordsSet();
            long startTime = System.currentTimeMillis();
            resetSearchTable();
            selectedTables.forEach(tableName -> {
                List<DBTableColumnModel> tableColumns = null;
                if (fillTableColCache != null && fillTableColCache.size() > 0) {
                    tableColumns = fillTableColCache.stream().filter(table -> table.getTableName().equals(tableName))
                            .collect(Collectors.toList());
                }
                if (tableColumns == null || tableColumns.size() == 0) {
                    tableColumns = owner.getDbTableService().getTableColumn(tableName);
                    // 缓存
                    addTableColCache(tableColumns);
                }
                tableColumns.forEach(tableColumn -> {
                    searchNum++;
                    addTableRow(tableColumn);
                });

                DBTableModel tableShow = owner.getSearchTables().stream().filter(table -> table.getTableName().equals(tableName))
                        .findFirst().get();
                tableShow.setColumns(tableColumns);
                exportTableList.add(tableShow);
            });
            long endTime = System.currentTimeMillis();
            showlog("解析" + selectedTables.size() + "个表的" + searchNum + "个字段(耗时" + (endTime - startTime) + "毫秒)。");

        } else {
            showlog("未选择表！");
        }
    }

    /**
     * 增加缓存
     * 
     * @Title addTableColCache
     * @author 吕凯
     * @date 2016年8月26日 上午10:10:40
     * @param tableColumns
     *            void
     */
    private void addTableColCache(List<DBTableColumnModel> tableColumns) {
        if (tableColumns != null) {
            fillTableColCache.addAll(tableColumns); // 缓存
            CacheUtil.put(ConfigProperties.CACHE_TABLE_COL, fillTableColCache);
        }
    }

    /**
     * 清空缓存
     * 
     * @Title clearTableColCache
     * @author 吕凯
     * @date 2016年8月26日 上午10:11:22 void
     */
    private void clearTableColCache() {
        fillTableColCache.clear(); // 缓存
        CacheUtil.remove(ConfigProperties.CACHE_TABLE_COL);
    }

    private List<DBTableColumnModel> getTableColCache() {
        List<DBTableColumnModel> cache = null;
        try {
            cache = CacheUtil.get(ConfigProperties.CACHE_TABLE_COL);
        } catch (Exception e) {
            log.error("获取表字段缓存失败！", e);
        } // 获得缓存
        if (cache == null) {
            cache = new ArrayList<>();
        }
        return cache;
    }

    /**
     * 设置表格宽度
     * 
     * @Title setTableColumWidth
     * @author 吕凯
     * @date 2016年8月23日 下午4:07:46 void
     */
    private void setTableColumWidth() {

        // TableColumn主要作用可以对表格中的某一列的属性进行编辑
//        TableColumn tableColumn = showSelectedTable.getColumn("部门");
        TableColumnModel tcm = showTable.getColumnModel();

        // 利用TableColumn类中的setCellEditor()方法来设置单元格的编辑器
        // DefaultCellEditor类可以将表格中的单元格设置成下拉框
        tcm.getColumn(JTableColumnModel.COLINDEX_JCB).setCellEditor(new DefaultCellEditor(comboBox));
        // 添加标格监听事件
        JTableUtil.fitTableColumns(showTable, new int[] { 30, 200, 120, 120, 120, 120, 120 });
    }

    public void addTableRow(DBTableColumnModel table) {
        showTableModel.addRow(JTableColumnModel.dbTableColModel2jTable(table, ++index));
//        defaultModel.addRow(new String[] { "" }); // 空行
    }

    /**
     * 添加打开文件动作监听
     * 
     * @Title addLogTAAction
     * @author 吕凯
     * @date 2016年8月25日 上午8:12:27 void
     */
    private void addOpenMenuAction() {
        outDicText.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger())
                    showMenu(e);
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger())
                    showMenu(e);
            }

            private void showMenu(MouseEvent e) {
                popup.show(e.getComponent(), e.getX(), e.getY());
            }
        });

    }
}
